﻿Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Collections.Specialized
Imports System.Configuration.Provider
Imports System.IO
Imports System.Linq
Imports System.Text
Imports System.Web
Imports System.Windows.Media.Imaging


Namespace Providers



    ''' <summary>
    ''' Manages storage of picture information in the file system
    ''' </summary>
    Public Class FileSystemPictureProvider
        Inherits PictureProvider



        Private _imagesPath As String

        Public ReadOnly Property ImagesPath() As String
            Get
                Return _imagesPath
            End Get
        End Property

        Public Overrides Sub Initialize(ByVal name As String, ByVal config As NameValueCollection)
            MyBase.Initialize(name, config)

            Dim s As String = config.Get("imagesPath")
            If s Is Nothing Then
                Throw New ProviderException("imagesPath is not set")
            End If

            If Not Directory.Exists(s) Then
                Throw New ProviderException("imagesPath directory does not exists")
            End If

            Dim info As New DirectoryInfo(s)
            _imagesPath = info.FullName
        End Sub




        Public Overrides Function GetPictureById(ByVal pictureId As String) As Picture
            Dim s As String = pictureId.Replace(";", "/")
            Dim path As String = HttpUtility.UrlDecode(New Uri(New Uri(ImagesPath, UriKind.Absolute), New Uri(s, UriKind.Relative)).AbsolutePath)

            If Not File.Exists(path) Then
                Return Nothing
            End If

            Dim p As Picture = PopulatePictureFromFileInfo(path)
            Return p
        End Function

        Public Overrides Function GetPictures() As List(Of Picture)
            Dim files As String() = Directory.GetFiles(ImagesPath, "*", SearchOption.AllDirectories)

            Dim list As New List(Of Picture)
            For Each f As String In files
                If f.EndsWith(".jpg", StringComparison.Ordinal) OrElse _
                   f.EndsWith(".png", StringComparison.Ordinal) OrElse _
                   f.EndsWith(".bmp", StringComparison.Ordinal) OrElse _
                   f.EndsWith(".gif", StringComparison.Ordinal) Then

                    list.Add(PopulatePictureFromFileInfo(f))
                End If
            Next

            Return list
        End Function

        Public Overrides Function GetPicturesByTag(ByVal tagName As String) As List(Of Picture)
            Return GetPictures.Where(Function(p) (p.Tags.Contains(tagName))).ToList
        End Function

        Private Function PopulatePictureFromFileInfo(ByVal filePath As String) As Picture
            Dim metadata As BitmapMetadata = GetBitmapMetadata(filePath)
            Dim info As New FileInfo(filePath)

            Dim p As New Picture()

            ' Set picture ID
            Dim uri As New Uri(ImagesPath)
            Dim relativeUri As Uri = uri.MakeRelativeUri(New Uri(info.FullName))
            Dim relativePath As String = relativeUri.ToString.Substring(0, relativeUri.ToString.LastIndexOf(".", StringComparison.Ordinal)).Replace("/", ";")
            p.Id = relativePath

            p.Tags = If(metadata.Keywords Is Nothing, Enumerable.Empty(Of String).ToArray, metadata.Keywords.ToArray())
            p.Title = If(String.IsNullOrEmpty(metadata.Title), info.Name, metadata.Title)
            p.DateCreated = info.CreationTime
            p.DateModified = info.LastWriteTime
            p.FileName = info.Name
            p.FileExtension = info.Extension
            p.ItemUrl = New Uri(info.FullName)
            p.Size = CInt(info.Length)
            p.Rating = metadata.Rating

            If Not String.IsNullOrEmpty(metadata.Comment) Then
                p.Comment = metadata.Comment
            End If

            Select Case p.FileExtension
                Case ".jpg"
                    p.MimeType = "image/jpeg"
                    Exit Select
                Case ".png"
                    p.MimeType = "image/png"
                    Exit Select
                Case ".gif"
                    p.MimeType = "image/gif"
                    Exit Select
                Case ".bmp"
                    p.MimeType = "image/bmp"
                    Exit Select
            End Select

            Return p
        End Function

        Private Shared Function GetBitmapMetadata(ByVal filePath As String) As BitmapMetadata
            Dim fs As New FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)
            Dim decoder As BitmapDecoder = BitmapDecoder.Create(fs, BitmapCreateOptions.None, BitmapCacheOption.Default)
            Dim frame As BitmapFrame = decoder.Frames(0)
            Dim metadata As BitmapMetadata = DirectCast(frame.Metadata, BitmapMetadata)
            fs.Dispose()
            Return metadata
        End Function

    End Class

End Namespace
